package com.ocean.array;

import java.util.Arrays;

/**
 * https://leetcode.cn/problems/squares-of-a-sorted-array/
 * <p>
 * 有序数组的平方
 * <p>
 * 给你一个按 非递减顺序 排序的整数数组 nums，返回 每个数字的平方 组成的新数组，要求也按 非递减顺序 排序。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [-4,-1,0,3,10]
 * 输出：[0,1,9,16,100]
 * 解释：平方后，数组变为 [16,1,0,9,100]
 * 排序后，数组变为 [0,1,9,16,100]
 * 示例 2：
 * <p>
 * 输入：nums = [-7,-3,2,3,11]
 * 输出：[4,9,9,49,121]
 *  
 * <p>
 * 提示：
 * <p>
 * 1 <= nums.length <= 104
 * -104 <= nums[i] <= 104
 * nums 已按 非递减顺序 排序
 *  
 * <p>
 * 进阶：
 * <p>
 * 请你设计时间复杂度为 O(n) 的算法解决本问题
 *
 * @author linmiaolai@sanyygp.com<br>
 * @version 1.0<br>
 * @date 2023/03/23 <br>
 */
public class SquaresOfASortedArray {

    public static void main(String[] args) {
        SquaresOfASortedArray sort = new SquaresOfASortedArray();
        int[] nums = {-4, -1, 0, 3, 10};
        int[] res = sort.sortedSquares2(nums);
        System.out.println(Arrays.toString(res));
    }

    /**
     * [-4,-1,0,3,10]
     *
     * @param nums
     * @return
     */
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] result = new int[n];
        int k = n - 1;
        for (int slow = 0, fast = n - 1; slow <= fast; ) {
            if (nums[slow] * nums[slow] < nums[fast] * nums[fast]) {
                result[k--] = nums[fast] * nums[fast];
                fast--;
            } else {
                result[k--] = nums[slow] * nums[slow];
                slow++;
            }
        }
        return result;
    }

    public int[] sortedSquares2(int[] nums) {
        // 找到负数位置
        int n = nums.length;
        int i = 0;
        for (; i < n; i++) {
            if (nums[i] >= 0) {
                break;
            }
        }
        // 计算
        int[] result = new int[n];
        for (int j = 0; j < n; j++) {
            result[j] = nums[j] * nums[j];
        }
        // 采用归并排序
        mergeSort(result, 0, i, n - 1);
        return result;
    }

    /**
     * {-4, -1, 0, 3, 10}
     * <p>
     * <p>
     * [16,1]
     * [0,9,100]
     *
     * @param nums
     * @param start
     * @param mid
     * @param end
     */
    private void mergeSort(int[] nums, int start, int mid, int end) {
        if (mid == 0) {
            return;
        }
        int[] temp = new int[end - start + 1];
        int left = mid - 1;
        int right = mid;
        for (int i = 0; i < temp.length; i++) {
            if (left < start) {
                // 说明左边跑完了
                temp[i] = nums[right++];
            } else if (right > end) {
                temp[i] = nums[left--];
            } else if (nums[left] < nums[right]) {
                temp[i] = nums[left--];
            } else {
                temp[i] = nums[right++];
            }
        }
        // 拷贝回去
        for (int i = 0; i < temp.length; i++) {
            nums[start + i] = temp[i];
        }
    }

}
